﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// BW = imregionalmin(I) computes the regional minima of I. 
    /// The output binary image BW has value 1 corresponding to the pixels of I that belong to regional minima and 0 otherwise. 
    /// BW is the same size as I.
    /// Regional minima are connected components of pixels with a constant intensity value, 
    /// and whose external boundary pixels all have a higher value.
    /// By default, imregionalmin uses 8-connected neighborhoods for 2-D images and 26-connected neighborhoods for 3-D images. 
    /// For higher dimensions, imregionalmin uses conndef(ndims(I),'maximal').
    /// BW = imregionalmin(I,conn) specifies the desired connectivity. 
    /// conn can have any of the following scalar values:
    /// 4, 8, 6, 16, 26
    /// </summary>
    public class ExperimentalEdgeFilter : BaseForeBackgroundColorFilter
    {
        //TODO: check if this can be deleted (inheritance)
        protected Dictionary<NEIGHBOUR, List<Point>> m_aNeighbour = new Dictionary<NEIGHBOUR, List<Point>>() { 
            {NEIGHBOUR.EIGHT, Definitions.EnvironmentPointListClockwise},
            {NEIGHBOUR.FOUR, Definitions.EnvironmentPointList4Clockwise}
        };

        //TODO: check if this can be deleted (inheritance)
        protected NEIGHBOUR m_NEIGHBOUR = NEIGHBOUR.EIGHT;


        /// <summary>
        /// Initializes a new instance of the <see cref="ImageRegionalMax"/> class.
        /// </summary>
        public ExperimentalEdgeFilter()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ImageRegionalMax"/> class.
        /// </summary>
        /// <param name="_imageRegionalMin">The _image regional min.</param>
        internal ExperimentalEdgeFilter(ExperimentalEdgeFilter _imageRegionalMin)
        {
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            int y = 0;
            int x = 0;
            int nHeight = _bitmap.Height;
            int nWidth = _bitmap.Width;

            Color[] aColor = new Color[m_aNeighbour[m_NEIGHBOUR].Count];

            new RoundColors(135).Execute(_bitmap);

            UnsafeBitmap bitmapCloned = (UnsafeBitmap)_bitmap.Clone();

            int nMin = 16777215;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    Color color = _bitmap.GetPixel(x, y);

                    nMin = color.ToArgb();

                    aColor = Segmentation.GetEnvironmentPixelColorArray(bitmapCloned, x, y, Definitions.EnvironmentPointList4Clockwise, aColor);

                    int nValue = 0;

                    bool bForeground = false;
                    int nCountMin = 0;
                    int nCountSame = 0;
                    foreach (Color colorEnvironment in aColor)
                    {
                        nValue = colorEnvironment.ToArgb();
                        if (nValue < nMin)
                        {
                            nCountMin++;
                        }
                        if (nValue == nMin)
                        {
                            nCountSame++;
                        }
                    }
                    bForeground = (nCountMin > 0 && (nCountSame + nCountMin > 3));

                    _bitmap.SetPixel(x, y, bForeground ? m_ColorForeground : m_ColorBackground);
                }
            }
            bitmapCloned.Dispose();
            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new ExperimentalEdgeFilter(this);
        }
    }
}
